package ca.unbc.cpsc672;

import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.wizard.IWizardPage;
import org.eclipse.jface.wizard.Wizard;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;

import ca.unbc.cpsc672.fuzzy.FuzzySet;
import ca.unbc.cpsc672.fuzzy.IOUtils;
import ca.unbc.cpsc672.fuzzy.function.MembershipFunction;
import ca.unbc.cpsc672.rcmd.RcmdOptions;

public class RestaurantRecommendationsWizard extends Wizard {
	class MapPage extends WizardPage {
		private int x;
		private int y;

		protected MapPage() {
			super("Map");
			setTitle("Where are you?");
			setDescription("We will recommand restaurants based on your current location");
		}

		@Override
		public void createControl(Composite parent) {
			final Image mapImg = new Image(parent.getDisplay(),
					RestaurantRecommendationsWizard.class
							.getResourceAsStream("citymap_phoenix_az.gif"));
			x = mapImg.getImageData().width / 2;
			y = mapImg.getImageData().height / 2;

			final Image markerImg = new Image(parent.getDisplay(),
					RestaurantRecommendationsWizard.class
							.getResourceAsStream("map.marker.small.hi.png"));
			Canvas canvas = new Canvas(parent, SWT.NONE);
			canvas.addPaintListener(new PaintListener() {

				@Override
				public void paintControl(PaintEvent e) {
					e.gc.drawImage(mapImg, 0, 0);
					e.gc.drawImage(markerImg, x
							- markerImg.getImageData().width / 4,
							y - markerImg.getImageData().height);
				}
			});

			canvas.addMouseListener(new MouseListener() {

				@Override
				public void mouseUp(MouseEvent e) {
					// TODO Auto-generated method stub

				}

				@Override
				public void mouseDown(MouseEvent e) {
					x = e.x;
					y = e.y;
					((Canvas) e.getSource()).redraw();
				}

				@Override
				public void mouseDoubleClick(MouseEvent e) {
					// TODO Auto-generated method stub

				}
			});
			setControl(canvas);
		}

		double getLatitude() {
			return 33.668852 + (33.668852 - 33.462594) / 291 * (59 - y);
		}

		double getLongitude() {
			return -112.108252 - (112.108252 - 112.037871) / 52 * (450 - x);
		}
	}

	class TimePage extends WizardPage {
		private Text txt1;
		private Text txt2;

		TimePage() {
			super("time");
			setTitle("Your interests");
			setDescription("We will recommand restaurants according to your interests");
		}

		@Override
		public void createControl(Composite parent) {
			Composite composite = new Composite(parent, SWT.NULL);
			composite.setLayout(new GridLayout(4, false));

			Label label = new Label(composite, SWT.NULL);
			GridData data = GUIUtils.buildGridData();
			data.horizontalSpan = 4;
			label.setLayoutData(data);
			label.setText("What time you plan to begin your dinner?(HH:MM)");
			txt1 = new Text(composite, SWT.NONE);
			txt1.setText("18");
			new Label(composite, SWT.NULL).setText(":");
			txt2 = new Text(composite, SWT.NONE);
			txt2.setText("00");

			setControl(composite);
		}

		public double getTime() {
			double hh = Double.parseDouble(txt1.getText());
			double mm = Double.parseDouble(txt2.getText());
			return hh + mm / 60;
		}
	}

	class InterestPage extends WizardPage {
		private Button[] btnAry = new Button[3];
		private String name;

		InterestPage(String name) {
			super("Questionnaire_" + name);
			this.name = name;
			setTitle("Your interests");
			setDescription("We will recommand restaurants according to your interests");
		}

		@Override
		public void createControl(Composite parent) {
			Composite composite = new Composite(parent, SWT.NULL);
			composite.setLayout(new GridLayout());

			new Label(composite, SWT.NULL).setText("How do you care about: "
					+ name);
			btnAry[0] = new Button(composite, SWT.RADIO);
			btnAry[0].setText("Don't Care");
			btnAry[1] = new Button(composite, SWT.RADIO);
			btnAry[1].setText("Normal");
			btnAry[1].setSelection(true);
			btnAry[2] = new Button(composite, SWT.RADIO);
			btnAry[2].setText("Very Care");

			setControl(composite);
		}

		public double getConcentrate() {
			if (btnAry[0].getSelection())
				return 0.5;
			else if (btnAry[2].getSelection())
				return 2;
			else
				return 1;
		}
	}

	class FuzzySetPage extends WizardPage {
		private FuzzySet fuzSet;
		private Button[] btnAry;

		FuzzySetPage(FuzzySet fuzSet) {
			super("Questionnaire_" + fuzSet.getName());
			this.fuzSet = fuzSet;
			setTitle("Your interests");
			setDescription("We will recommand restaurants according to your interests");
		}

		@Override
		public void createControl(Composite parent) {
			Composite composite = new Composite(parent, SWT.NULL);
			GridLayout gridLayout = new GridLayout();
			composite.setLayout(gridLayout);

			new Label(composite, SWT.NULL)
					.setText("Do you care about the popularity?");
			Collection<String> lv = fuzSet.getAllLinguisticVariables();
			btnAry = new Button[lv.size() + 1];
			int i = 0;
			for (String str : lv) {
				btnAry[i] = new Button(composite, SWT.RADIO);
				btnAry[i].setText(str);
				i++;
			}
			btnAry[i] = new Button(composite, SWT.RADIO);
			btnAry[i].setText("Any");
			btnAry[i].setSelection(true);
			setControl(composite);
		}

		public MembershipFunction getSelection() {
			for (Button btn : btnAry) {
				if (btn.getSelection()) {
					return fuzSet.getMembershipFunction(btn.getText());
				}
			}
			return null;
		}
	}

	private Map<String, FuzzySet> setMap = new HashMap<>();

	public RestaurantRecommendationsWizard() throws IOException {
		this.setMap = IOUtils.loadFuzzySet();
	}

	@Override
	public void addPages() {
		addPage(new MapPage());
		addPage(new InterestPage("Distance"));
		addPage(new TimePage());
		addPage(new InterestPage("Time"));
		addPage(new InterestPage("Taste"));
		addPage(new InterestPage("Service"));
		addPage(new FuzzySetPage(setMap.get("popularity")));
		addPage(new InterestPage("Popularity"));
		setWindowTitle("Recommendations Wizard");
	}

	@Override
	public boolean performFinish() {
		IWizardPage[] pages = getPages();
		RcmdOptions options = new RcmdOptions();
		// map
		options.latitude = ((MapPage) pages[0]).getLatitude();
		options.longititude = ((MapPage) pages[0]).getLongitude();
		// c distance
		options.cDistance = ((InterestPage) pages[1]).getConcentrate();
		// time
		options.time = ((TimePage) pages[2]).getTime();
		// c time
		options.cTime = ((InterestPage) pages[3]).getConcentrate();
		// c taste
		options.cTaste = ((InterestPage) pages[4]).getConcentrate();
		// c service
		options.cService = ((InterestPage) pages[5]).getConcentrate();
		// popularity
		options.mf = ((FuzzySetPage) pages[6]).getSelection();
		// c popularity
		options.cPopularity = ((InterestPage) pages[7]).getConcentrate();

		RcmdProgressBar bar = new RcmdProgressBar(getShell(), options);
		bar.setBlockOnOpen(true);
		bar.open();
		
		Dialog window = new RcmdDialog(getShell(), bar.getResult());
		window.setBlockOnOpen(true);
		window.open();
		return true;
	}

}
